package com.ren.article.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ren.article.constant.CachePrefix;
import com.ren.article.entity.ReclArticle;
import com.ren.article.entity.vo.ReclArticleQueryVo;
import com.ren.article.entity.vo.ReclArticleVo;
import com.ren.article.mapper.ReclArticleMapper;
import com.ren.article.service.ReclArticleCollectionService;
import com.ren.article.service.ReclArticleCommentService;
import com.ren.article.service.ReclArticlePraiseService;
import com.ren.article.service.ReclArticleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ren.cache.annotation.MultiCache;
import com.ren.feign.api.recl_user.ReclUserClient;
import com.ren.feign.entity.ReclUserVo;
import com.ren.utils.page.PageItem;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author RZY
 * @since 2022-07-20
 */
@Service
public class ReclArticleServiceImpl extends ServiceImpl<ReclArticleMapper, ReclArticle> implements ReclArticleService {

    @Autowired
    ReclArticlePraiseService articlePraiseService;

    @Autowired
    ReclArticleCollectionService articleCollectionService;

    @Autowired
    ReclArticleCommentService articleCommentService;

    @Autowired
    ReclUserClient userClient;

    /**
     * @param id FM记录id
     * @return ReclArticle对象
     */
    @Override
    public ReclArticleVo getArticleVoById(Long id) {
        //获取FM对象
        ReclArticle reclArticle = getArticleById(id);
        //远程feign获取上传用户信息
        ReclUserVo userVo = userClient.getRemoteArticleUserInfo(reclArticle.getCreateUserId());
        ReclArticleVo reclArticleVo = new ReclArticleVo();
        //封装ReclArticleVO
        BeanUtils.copyProperties(userVo, reclArticleVo);
        BeanUtils.copyProperties(reclArticle, reclArticleVo);
        return reclArticleVo;
    }

    /**
     * 获取FM的封装对象
     *
     * @param id
     * @return
     */
    @MultiCache(cacheGroup = "recl_article",
            prefixKey = CachePrefix.ARTICLE_ITEM_KEY_PREFIX,
            key = "#id",
            expireTime = 70,
            sync = true)
    private ReclArticle getArticleById(Long id) {
        return this.getById(id);
    }

    /**
     *
     * @param reclArticle 需要更新reclFM
     * @return 返回更新结果
     */
    @Override
    public boolean updateArticleById(ReclArticle reclArticle) {
        return this.updateById(reclArticle);
    }

    /**
     *
     * @param id 需要删除FM对应id
     * @return 返回删除结果
     */
    @Override
    public boolean delArticleById(Long id) {
        return this.removeById(id);
    }

    /**
     *
     * @param reclArticle 需要添加的reclFM
     * @return 返回添加结果
     */
    @Override
    public boolean addArticle(ReclArticle reclArticle) {
        return this.saveOrUpdate(reclArticle);
    }

    /**
     * @param userId 用户id
     * @return 返回用户点赞的reclArticle
     */
    @Override
    public List<ReclArticleVo> getArticleByPraiseUserId(Long userId) {
        List<ReclArticle> reclArticles = this.baseMapper.getArticleByPraiseUserId(userId);
        //获取上传用户的id
        List<Long> userIds = reclArticles.stream().map(ReclArticle::getCreateUserId).collect(Collectors.toList());
        //openFeign远程调用并封装ReclArticleVos
        return getArticleVos(userIds, reclArticles);
    }

    /**
     * @param userId 用户id
     * @return 返回用户评论的reclArticle
     */
    @Override
    public List<ReclArticleVo> getArticleByCommentUserId(Long userId) {
        List<ReclArticle> reclArticles = this.baseMapper.getArticleByCommentUserId(userId);
        //获取上传用户的id
        List<Long> userIds = reclArticles.stream().map(ReclArticle::getCreateUserId).collect(Collectors.toList());
        //openFeign远程调用并封装ReclArticleVos
        return getArticleVos(userIds, reclArticles);
    }

    /**
     * @param userId 用户id
     * @return 返回用户收藏的reclArticle
     */
    @Override
    public List<ReclArticleVo> getArticleByCollectionUserId(Long userId) {
        List<ReclArticle> reclArticles = this.baseMapper.getArticleByCollectionUserId(userId);
        //获取上传用户的id
        List<Long> userIds = reclArticles.stream().map(ReclArticle::getCreateUserId).collect(Collectors.toList());
        //openFeign远程调用并封装ReclArticleVos
        return getArticleVos(userIds, reclArticles);
    }

    /**
     *
     * @param reclArticleQueryVo 筛选前台参数封装
     * @param current   查询页号
     * @param limit   每页数据量
     * @return 返回封装前台分页对象pageItem
     */
    @Override
    public PageItem<ReclArticleVo> getFrontArticleOfPage(ReclArticleQueryVo reclArticleQueryVo, long current, long limit) {
        //创建分页对象
        Page<ReclArticle> articlePage = new Page<>();
        //获取筛选参数
        String articleClassify = reclArticleQueryVo.getArticleClassify();

        QueryWrapper<ReclArticle> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("gmt_create");
        wrapper.eq("status", "verify");

        if(!StringUtils.isEmpty(articleClassify)) wrapper.like("article_classify", articleClassify);

        //查询分页page
        this.page(articlePage, wrapper);

        List<ReclArticle> records = articlePage.getRecords();

        long total = articlePage.getTotal();

        return getPageItem(records, total);
    }

    /**
     *
     * @param records 需要封装的分页记录
     * @param total 需要封装的总页数
     * @return 返回封装分页对象ReclArticleVo
     */
    private PageItem<ReclArticleVo> getPageItem(List<ReclArticle> records, long total) {

        //封装ReclArticleVo集合
        List<ReclArticleVo> reclArticleVos = new ArrayList<>();
        //当没有记录时，直接返回默认PageItem
        if(records.isEmpty()) return new PageItem<ReclArticleVo>().setPageRecords(reclArticleVos)
                .setTotal(0);

        //利用stream流获取records中的上传用户id
        List<Long> userIds = records.stream().map(ReclArticle::getCreateUserId).collect(Collectors.toList());
        //远程调用feign接口批量擦查询用户信息
        List<ReclUserVo> userVos = userClient.getRemoteArticleUsersInfo(userIds);

        for(int i = 0; i < records.size(); i++) {
            ReclArticleVo reclArticleVo = new ReclArticleVo();
            BeanUtils.copyProperties(userVos.get(i), reclArticleVo);
            BeanUtils.copyProperties(records.get(i), reclArticleVo);
            reclArticleVos.add(reclArticleVo);
        }
        //封装分页对象pageItem
        return new PageItem<ReclArticleVo>().setPageRecords(reclArticleVos)
                .setTotal(total);
    }

    /**
     *
     * @param userIds 批量查询的用户id
     * @param reclArticles 需要封装的reclArticles
     * @return 返回封装集合List<ReclArticleVo>
     */
    @Override
    public List<ReclArticleVo> getArticleVos(List<Long> userIds, List<ReclArticle> reclArticles) {
        //封装ReclArticleVo集合
        List<ReclArticleVo> reclArticleVos = new ArrayList<>();
        //远程调用feign接口批量擦查询用户信息
        List<ReclUserVo> userVos = userClient.getRemoteArticleUsersInfo(userIds);

        for(int i = 0; i < reclArticles.size(); i++) {
            ReclArticleVo reclArticleVo = new ReclArticleVo();
            BeanUtils.copyProperties(userVos.get(i), reclArticleVo);
            BeanUtils.copyProperties(reclArticles.get(i), reclArticleVo);
            reclArticleVos.add(reclArticleVo);
        }
        return reclArticleVos;
    }

    /**
     *
     * @param reclArticleQueryVo 筛选参数封装
     * @param current   查询页号
     * @param limit   每页数据量
     * @return 返回封装分页对象pageItem
     */
    @Override
    public PageItem<ReclArticleVo> getArticleOfPage(ReclArticleQueryVo reclArticleQueryVo, long current, long limit) {
        //创建分页对象
        Page<ReclArticle> articlePage = new Page<>();
        //获取筛选参数
        String articleTitle = reclArticleQueryVo.getArticleTitle();
        String start = reclArticleQueryVo.getStart();
        String end = reclArticleQueryVo.getEnd();
        String status = reclArticleQueryVo.getStatus();

        QueryWrapper<ReclArticle> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("gmt_create");

        if(!StringUtils.isEmpty(articleTitle)) wrapper.like("article_title", articleTitle);

        if(!StringUtils.isEmpty(start)) wrapper.ge("gmt_create", start);

        if(!StringUtils.isEmpty(end)) wrapper.le("gmt_modified", end);

        if(!StringUtils.isEmpty(status)) wrapper.eq("status", status);
        //查询分页page
        this.page(articlePage, wrapper);

        List<ReclArticle> records = articlePage.getRecords();

        long total = articlePage.getTotal();

        return getPageItem(records, total);
    }
}
